/*
Copyright 2008  Four Roads LLC conact@4-roads.com

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either 
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections;
using System.Web.UI;
using System.Web.UI.WebControls;
using CommunityServer.Components;
using CommunityServer.Controls;
using System.Reflection;
using System.Reflection.Emit;
using System.ComponentModel;
using System.IO;

namespace FourRoads.Links.Controls
{
	public class SkinExtensionControl : TemplatedWebControl
	{
		private SkinExtension _InsertSkinDetails = null;
		public SkinExtensionControl(SkinExtension item)
		{
			_InsertSkinDetails = item;
			ExternalSkinFileName = "Skin-" + _InsertSkinDetails.SkinName + ".ascx";
		}

		protected override void AttachChildControls()
		{
			//Hmm what to do inhere??
		}

		protected Post _Post;
		public Post CurrentPost
		{
			get
			{
				return _Post;
			}

			set
			{
				_Post = value;
			}
		}

		private PropertyInfo GetInnerProperty(string propertExpression , object obj , out object finalObject)
		{
			Type currentType = obj.GetType();
			string []callStack = propertExpression.Split(new char[]{'.'});
			PropertyInfo pi = currentType.GetProperty(callStack[0]);

			finalObject = obj;

			for(int i=0;i < callStack.Length-1;i++)
			{			
				MethodInfo mi = pi.GetGetMethod(false);

				finalObject = mi.Invoke(obj , new object[0]);

				currentType = finalObject.GetType();

				pi = currentType.GetProperty(callStack[i+1]);
			}

			return pi;
		}

		private void RetrievePropertyValue( string name  , string propertExpression ,Control ctrl)
		{
			object output;
			PropertyInfo pi = GetInnerProperty(propertExpression , ctrl , out output);

			string itemValue = CurrentPost.GetExtendedAttribute( name );

			if (itemValue != null)
			{
				System.Type destType = pi.PropertyType;
				System.Type srcType = itemValue.GetType();

				TypeConverter ti = TypeDescriptor.GetConverter(srcType);
							
				try
				{
					if (ti.CanConvertTo(destType))
					{
						pi.SetValue( output , ti.ConvertTo( itemValue , destType)  , null);
					}
					else
					{
						TypeConverter ti2 = TypeDescriptor.GetConverter(destType);
						if (ti2.CanConvertFrom(srcType))
						{
							pi.SetValue( output ,  ti2.ConvertFrom( itemValue ) , null);
						}
					}
				}
				catch(Exception )
				{
					//Just deaulty it
				}
			}
		}

		public override void DataBind()
		{
			base.DataBind ();

			if (CurrentPost != null)
			{
				//Get the values of the controls from the controls on the page
				foreach(SkinExtensionProperty prop in _InsertSkinDetails.Properties)
				{
					Control ctrl = FindControl(prop.Name);

					Type controlType = ctrl.GetType();
					
					//If dataitem isn't empty then this is used to select the value in the control
					if (prop.DataItem != string.Empty)
					{
						RetrievePropertyValue( "$$DI$$" + prop.Name  , prop.DataItem , ctrl);
					}
					else //just use the value
					{
						RetrievePropertyValue( "$$" + prop.Name  , prop.DataValue , ctrl);
					}
				}
			}
		}

		public void SaveChanges()
		{
			if (CurrentPost != null)
			{
				//Get the values of the controls from the controls on the page
				foreach(SkinExtensionProperty prop in _InsertSkinDetails.Properties)
				{
					Control ctrl = FindControl(prop.Name);
					//If DataItem exists then save it in its own property
					if (prop.DataItem != string.Empty)
					{
						StorePropertyValue( "$$DI$$" + prop.Name  , prop.DataItem , ctrl);
					}

					StorePropertyValue( "$$" + prop.Name  , prop.DataValue , ctrl);
				}
			}
		}

	

		private void StorePropertyValue( string name  , string propertExpression ,Control ctrl)
		{
			object output;
			PropertyInfo pi = GetInnerProperty(propertExpression , ctrl, out output);  //propertExpression

			object [] index = null;
			object data = pi.GetValue (output ,  index);

			if (data != null)
			{
				System.Type srcType = pi.PropertyType;
				System.Type destType = typeof(string);

				TypeConverter ti = TypeDescriptor.GetConverter(destType);

				if (ti.CanConvertFrom(srcType))
				{
					CurrentPost.SetExtendedAttribute(name , (string)ti.ConvertFrom(data));
				}
				else
				{
					TypeConverter ti2 = TypeDescriptor.GetConverter(srcType);
					if (ti.CanConvertTo(destType))
					{
						CurrentPost.SetExtendedAttribute(name , (string)ti.ConvertTo(data , destType));
					}
				}
			}
		}
		/// <summary>
		/// No Being Span
		/// </summary>
		/// <param name="writer"></param>
		public override void RenderBeginTag(System.Web.UI.HtmlTextWriter writer)
		{
			//we don't need a span tag
		}

		/// <summary>
		/// No End Span
		/// </summary>
		/// <param name="writer"></param>
		public override void RenderEndTag(System.Web.UI.HtmlTextWriter writer)
		{
			//we don't need a span tag
		}

		protected override string SkinFolder 
		{
			get 
			{
				return Path.Combine (base.SkinFolder , "ResourceLinks/"); //TODO Use correct skin folder
			}
		}
	}
}
